<!DOCTYPE html>

<html>
    <head>
        <meta charset="UTF-8">
        <title>遍历文档</title>
    </head>
    <body>
        <h1>遍历文档</h1>
        <ul>
            <li>Element.prototype.innerHTML 可以获得元素内部的HTML片段</li>
            <li>Element.prototype.outerHTML 可以获得元素及其内部HTML片段</li>
        </ul>
        <p>请在浏览器终端中查看运行结果</p>

        <script>
            const types = {
                '1': 'ELEMENT_NODE',
                '2': 'ATTRIBUTE_NODE',
                '3': 'TEXT_NODE',
                '8': 'COMMENT_NODE',
                '9': 'DOCUMENT_NODE',
                '10': 'DOCUMENT_TYPE_NODE'
            }
        
            function traversal(node) {
                // 输出节点名称、类型
                console.log( node.nodeName, types[ node.nodeType ] );
                // 处理属性(元素类型的节点有属性)
                if( node.hasAttributes && node.hasAttributes() ){
                    let attrs = node.attributes;
                    Array.from(attrs).forEach( e => {
                        console.log( '\t', e.nodeName , e.nodeValue , types[ e.nodeType ]);
                    });
                }
                // 处理子节点
                if( node.hasChildNodes() ) {
                    let childs = node.childNodes;
                    // 输出元素节点中的纯文本内容
                    if( node.nodeType === Node.ELEMENT_NODE ) {
                        // 若当前节点仅存在单个文本子节点
                        if( childs.length === 1 && childs[0].nodeType === Node.TEXT_NODE ) {
                            // 则通过当前节点的 innerHTML 属性获取文本内容
                            console.log('\t', node.innerHTML ); // Element.prototype.innerHTML
                            return;
                        }
                    }
                    Array.from(childs).forEach( e => {
                        traversal(e);
                    });
                }
            }
        
            traversal(document);
        </script>
    </body>
</html>

